%% Author: maciek
%% Created: 16-04-2011
%% Description: TODO: Add description to iax_peer
-module(iax_peer).
-behaviour(gen_server).
-compile(export_all).
%%
%% Include files
%%
-include("iax2_common.hrl").
-record(iaxpeerstate,{	peerservername,
						hostaddr,
						hostport,
						username, 
						password,
						register, 
						callcontrollers}).

%% -record(make_call_req,{calleridname,
%% 					   calleridnum,
%% 					   extension,
%% 					   context}).

-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3,make_call/2,call_hanged_up/2,
		 get_peer_host_addr/1,get_peer_host_port/1,get_peer_password/1,get_peer_username/1]).

-export([]).

init([Hostaddr,Hostport,Username,Password,Register,PeerServerName]) ->
	State = #iaxpeerstate{hostaddr=Hostaddr,
						  hostport=Hostport,
						  username=Username,
						 
						  register=Register,password=Password,
						  callcontrollers=[],
						  peerservername=PeerServerName},
	
	
	{ok,State}.

start_link(Hostaddr,Hostport,Username,Password,Register) ->
	PeerServerName = list_to_atom("iax_peer_"++Username++"@"++Hostaddr),
	{ok,Pid}=gen_server:start_link({local,PeerServerName},?MODULE, [Hostaddr,Hostport,Username,Password,Register,PeerServerName], []),
	{PeerServerName,Pid}.
get_peer_host_addr(PeerServerName) ->
	gen_server:call(PeerServerName, get_peer_host_addr).
get_peer_host_port(PeerServerName) ->
	gen_server:call(PeerServerName, get_peer_host_port).
get_peer_username(PeerServerName) ->
	gen_server:call(PeerServerName, get_peer_username).
get_peer_password(PeerServerName) ->
	gen_server:call(PeerServerName, get_peer_password).
stop(PeerServerName) ->
	gen_server:call(PeerServerName, terminate).

call_hanged_up(PeerServerName,CallControlerName) ->
	gen_server:call(PeerServerName, {call_hanged_up,CallControlerName}).


make_call(Req = #make_call_req{},PeerServerName) ->
	gen_server:call(PeerServerName, {make_call,Req}).

	
	
handle_call({call_hanged_up,CallControlerName},_From,State) ->
	io:format("Hanged up for peer ~n"),
	{Pid,_} = lists:keyfind(CallControlerName, 2, State#iaxpeerstate.callcontrollers),
	Pid ! callhangedup,
	{reply,ok,State};
handle_call(terminate,_From,State) ->
	{stop,normal,State};
handle_call({make_call,Req},{CallingPid,Tag},State) ->
	io:format("Spawning new call controller for requesting PID ~p~n",[CallingPid]),
	%spawn new call controller
	SrcCallId = src_call_id_generator:allocsrccallid(),
	CallControllerName = call_controller:start_link(State#iaxpeerstate.peerservername,SrcCallId,State#iaxpeerstate.username,
													State#iaxpeerstate.password,State#iaxpeerstate.hostaddr,
													State#iaxpeerstate.hostport),
	NewState = State#iaxpeerstate{callcontrollers=[{CallingPid,CallControllerName}|State#iaxpeerstate.callcontrollers]},
	io:format("Making call ~p using controller ~p ~n",[Req,CallControllerName]),
	call_controller:place_call(CallControllerName,Req#make_call_req.calleridname,
							   					Req#make_call_req.calleridnum,
							   					Req#make_call_req.extension,
							   					Req#make_call_req.context),
	{reply,CallControllerName,NewState};
handle_call(get_peer_host_addr,_From,State)  ->
	{reply,State#iaxpeerstate.hostaddr,State};

handle_call(get_peer_host_port,_From,State)  ->
	{reply,State#iaxpeerstate.hostaddr,State};

handle_call(get_peer_username,_From,State)  ->
	{reply,State#iaxpeerstate.username,State};

handle_call(get_peer_password,_From,State)  ->
	{reply,State#iaxpeerstate.password,State}.

%% --------------------------------------------------------------------
%% Function: handle_cast/2
%% Description: Handling cast messages
%% Returns: {noreply, State}          |
%%          {noreply, State, Timeout} |
%%          {stop, Reason, State}            (terminate/2 is called)
%% --------------------------------------------------------------------
handle_cast(_Msg, State) ->
    {noreply, State}.

%% --------------------------------------------------------------------
%% Function: handle_info/2
%% Description: Handling all non call/cast messages
%% Returns: {noreply, State}          |
%%          {noreply, State, Timeout} |
%%          {stop, Reason, State}            (terminate/2 is called)
%% --------------------------------------------------------------------
handle_info(_Info, State) ->
    {noreply, State}.

%% --------------------------------------------------------------------
%% Function: terminate/2
%% Description: Shutdown the server
%% Returns: any (ignored by gen_server)
%% --------------------------------------------------------------------
terminate(_Reason, State) ->
	io:format("Terminatin peer ~p~nCleaning up call controllers~n",[State#iaxpeerstate.peerservername]),
	lists:foreach(fun({_Pid,CallCName}) -> call_controller:stop(CallCName) end, State#iaxpeerstate.callcontrollers),
    ok.

%% --------------------------------------------------------------------
%% Func: code_change/3
%% Purpose: Convert process state when code is changed
%% Returns: {ok, NewState}
%% --------------------------------------------------------------------
code_change(OldVsn, State, Extra) ->
    {ok, State}.


